/**
 * 
 */
package com.airlines.common;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author xxxx
 * @date 2017年3月20日
 * @company xxxx Airlines
 * @description
 */
public class BeanFiledUtils {
	private static final Logger logger = LoggerFactory.getLogger(BeanFiledUtils.class);
	/** 
	 * 根据属性名获取属性值 
	 * */  
	   public static Object getFieldValueByName(String fieldName, Object o) {  
	       try {    
	           String firstLetter = fieldName.substring(0, 1).toUpperCase();    
	           String getter = "get" + firstLetter + fieldName.substring(1);    
	           Method method = o.getClass().getMethod(getter, new Class[] {});    
	           Object value = method.invoke(o, new Object[] {});    
	           return value;    
	       } catch (Exception e) {    
	          return getFieldValueByNameNotUpperCase(fieldName, o);
	       }    		   
	   }  
	   
	   /**
	    * 为了适应驼峰命名的另外一种规则
	    * @param fieldName
	    * @param o
	    * @return
	    */
	   public static Object getFieldValueByNameNotUpperCase(String fieldName, Object o) {  
	       try {      
	           String getter = "get"  + fieldName;    
	           Method method = o.getClass().getMethod(getter, new Class[] {});    
	           Object value = method.invoke(o, new Object[] {});    
	           return value;    
	       } catch (Exception e) {    
	          TraceUtil.error(logger, e);  
	           return null;    
	       }    
	   }  
	     
	   /** 
	    * 获取属性名数组 
	    * */  
	   public  static String[] getFiledName(Object o){  
	    Field[] fields=o.getClass().getDeclaredFields();  
	        String[] fieldNames=new String[fields.length];  
	    for(int i=0;i<fields.length;i++){  
	        System.out.println(fields[i].getType());  
	        fieldNames[i]=fields[i].getName();  
	    }  
	    return fieldNames;  
	   }  
	     
	   /** 
	    * 获取属性类型(type)，属性名(name)，属性值(value)的map组成的list 
	    * */  
	@SuppressWarnings({ "unused", "rawtypes", "unchecked" })
	public static List getFiledsInfo(Object o){  
	    Field[] fields=o.getClass().getDeclaredFields();  
	        String[] fieldNames=new String[fields.length];  
	        List list = new ArrayList();  
	        Map infoMap=null;  
	    for(int i=0;i<fields.length;i++){  
	        infoMap = new HashMap();  
	        infoMap.put("type", fields[i].getType().toString());  
	        infoMap.put("name", fields[i].getName());  
	        infoMap.put("value", getFieldValueByName(fields[i].getName(), o));  
	        list.add(infoMap);  
	    }  
	    return list;  
	   }  
	     
	   /** 
	    * 获取对象的所有属性值，返回一个对象数组 
	    * */  
	public static Object[] getFiledValues(Object o){  
	    String[] fieldNames=getFiledName(o);  
	    Object[] value=new Object[fieldNames.length];  
	    for(int i=0;i<fieldNames.length;i++){  
	        value[i]=getFieldValueByName(fieldNames[i], o);  
	    }  
	    return value;  
	   }

	/**
	 * 根据属性名，获取对象的属性值
	 * 该属性可以没有get方法
	 * @param obj
	 * @param fieldName
	 * @return
	 * @throws Exception
	 */
	public static Object forceGetFieldValue(Object obj, String fieldName) throws Exception {
		if(obj == null || fieldName == null || fieldName == ""){
			return null;
		}
		//优化，可以获取属性类属性名称，用.的形式调用
		int splitIndex = fieldName.indexOf(".");
		String fieldNameParent = null;
		String fieldNameSub = null;
		if(splitIndex > 0){
			fieldNameParent = fieldName.substring(0, splitIndex);
			fieldNameSub =  fieldName.substring(splitIndex+1, fieldName.length());
		}else{
			fieldNameParent = fieldName;
		}
		
		//优化获取可以获取父类的属性 by xxxx 2017年9月21日15:07:57
		Field field = null;
		Class<?> clazz =  obj.getClass();
		for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				field = clazz.getDeclaredField(fieldNameParent);
			} catch (Exception e) {
			}
		}
		
		Object object = null;
		boolean accessible = field.isAccessible();
		if (!accessible) {
			// 如果是private,protected修饰的属性，需要修改为可以访问的
			field.setAccessible(true);
			object = field.get(obj);
			// 还原private,protected属性的访问性质
			field.setAccessible(accessible);
		}else{
			object = field.get(obj);
		}
		
		if(fieldNameSub == null){
			return object;
		}else{
			return forceGetFieldValue(object,fieldNameSub);
		}
		
	}

	
	/**
	 * 根据属性名，属性值，将对象属性赋值
	 * 可以没有set方法
	 * @param obj
	 * @param fieldName
	 * @param fieldValue
	 * @throws Exception
	 */
	public static void forceSetFieldValue(Object obj, String fieldName,Object fieldValue) throws Exception {

		
		//优化获取可以获取父类的属性 by xxxx 2017年9月21日15:07:57
		Field field = null;
		Class<?> clazz =  obj.getClass();
		for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				field = clazz.getDeclaredField(fieldName);
			} catch (Exception e) {
			}
		}
		
		boolean accessible = field.isAccessible();
		if (!accessible) {
			// 如果是private,protected修饰的属性，需要修改为可以访问的
			field.setAccessible(true);
			field.set(obj, fieldValue);
			// 还原private,protected属性的访问性质
			field.setAccessible(accessible);
		}else{
			field.set(obj, fieldValue);
		
		}
	}
	
}
